﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using App1AppHandler;
using System.IO;
using System.Xml;
using System.Net.Sockets;
using System.Data.SqlClient;
using Reborn_Server.App1AppHandler;

namespace Reborn_WorldServer.App1AppHandler
{
    public class ChatChannelManager
    {
        private List<string> channels = new List<string>();
        private Character character;

        public ChatChannelManager(Character character)
        {
            this.character = character;

            //LOAD ITEMS
            SqlConnection MyCon = new SqlConnection(Managers.DBConnectionString);
            SqlCommand SQLCom = new SqlCommand("Characters_ChatChannels_Select", MyCon);
            SQLCom.CommandType = System.Data.CommandType.StoredProcedure;
            SQLCom.Parameters.AddWithValue("@CharacterID", character.ID);

            MyCon.Open();
            SqlDataReader SDR = SQLCom.ExecuteReader();

            while (SDR.Read())
            {
                string channel = SDR["ChannelName"].ToString();
                channels.Add(channel);                
            }
            SDR.Close();
            MyCon.Close();
            MyCon.Dispose();
            getChannels();
        }

        public void sendLoginNotifications()
        {
            //Copy channels so we dont double lock (sending messages will lock the characterManager
            List<string> channelsCopy = new List<string>();
            lock (channels)
            {
                foreach (string c in channels)
                    channelsCopy.Add(c);
            }
            foreach (string c in channelsCopy)
            {
                sendJoinChannelNotification(c.ToUpper());
                character.SendMessage("Joined Channel : (" + (channelsCopy.IndexOf(c.ToUpper()) + 1).ToString() + " - " + c.ToUpper() + ")  Type /" + (channelsCopy.IndexOf(c.ToUpper()) + 1).ToString() + " to send messages.", "server");
            }
        }

        public void sendLogoutNotifications()
        {
            //Copy channels so we dont double lock (sending messages will lock the characterManager
            List<string> channelsCopy = new List<string>();
            lock (channels)
            {
                foreach (string c in channels)
                    channelsCopy.Add(c);
            }
            foreach (string c in channelsCopy)
                sendLeaveChannelNotification(c.ToUpper());
        }

        public void tryRecieveMessage(string channel, string from, string message, string itemLinksXml)
        {
            lock (channels)
            {
                foreach (string c in channels)
                {
                    if (c.ToUpper() == channel.ToUpper())
                    {
                        Message msg = new Message();
                        msg.itemLinksXml = itemLinksXml;
                        msg.Text = (channels.IndexOf(c) + 1).ToString() + " - " + c.ToUpper() + " - " + from + ": " + message;
                        msg.Type = "channel";
                        msg.CreatureID = character.CreatureID;


                        character.AddMessage(msg);

                        break;
                    }
                }
            }
        }

        public void sendChannelMessage(string channel, string message, string itemLinksXml)
        {
            bool inChannel = false;
            lock (channels)
            {
                foreach (string c in channels)
                {
                    if (c.ToUpper() == channel.ToUpper())
                    {
                        inChannel = true;
                        break;
                    }
                } 
            }
            if (inChannel)
            {
                Managers.characterManager.recieveChannelMessage(channel, character.Name, message, itemLinksXml);
                Managers.BeginSendToPrimary("<sendchannelmessage channel=\"" + channel + "\" from=\"" + character.Name + "\" ><txt>" + Message.escapeXmlText(message) + "</txt>" + itemLinksXml + "</sendchannelmessage>");
            }
        }

        public void tryRecieveJoinNotification(string channel, string from)
        {
            bool sendMessage = false;
            int channelIndex = 0;
            string channelName = "";
            lock (channels)
            {
                foreach (string c in channels)
                {
                    if (c.ToUpper() == channel.ToUpper())
                    {
                        sendMessage = true;
                        channelIndex = channels.IndexOf(c);
                        channelName = c.ToUpper();
                        break;
                    }
                }
            }
            if (sendMessage == true)
                character.SendMessage((channelIndex + 1).ToString() + " - " + channelName + ": " + from + " has joined the channel.", "channel");
        }

        public void tryRecieveLeaveNotification(string channel, string from)
        {
            bool sendMessage = false;
            int channelIndex = 0;
            string channelName = "";

            lock (channels)
            {
                foreach (string c in channels)
                {
                    if (c.ToUpper() == channel.ToUpper())
                    {
                        sendMessage = true;
                        channelIndex = channels.IndexOf(c);
                        channelName = c.ToUpper();
                        break;
                    }
                }
            }
            if (sendMessage == true)
                character.SendMessage((channelIndex + 1).ToString() + " - " + channelName + ": " + from + " has left the channel.", "channel");
        }

        public void sendLeaveChannelNotification(string channel)
        {
            Managers.characterManager.recieveLeaveChannelNotification(channel, character.Name);
            Managers.BeginSendToPrimary("<sendchannelleave channel=\"" + channel + "\" from=\"" + character.Name + "\" />");
        }
        public void sendJoinChannelNotification(string channel)
        {
            Managers.characterManager.recieveJoinChannelNotification(channel.ToUpper(), character.Name);
            Managers.BeginSendToPrimary("<sendchanneljoin channel=\"" + channel + "\" from=\"" + character.Name + "\" />");
        }

        public void joinChannel(string channel)
        {
            bool channelAdded = false;
            lock (channels)
            {
                if (channels.Contains(channel.ToUpper()) == false)
                {
                    channels.Add(channel.ToUpper());
                    channelAdded = true;
                }
            }
            if (channelAdded)
            {
                character.SendMessage("Joined Channel : (" + (channels.IndexOf(channel.ToUpper()) + 1).ToString() + " - " + channel.ToUpper() + ")  Type /" + (channels.IndexOf(channel.ToUpper()) + 1).ToString() + " to send messages.", "server");
                sendJoinChannelNotification(channel.ToUpper());
                getChannels();
            }
        }
        public void leaveChannel(string channel)
        {
            bool channelRemoved = false;
            lock (channels)
            {
                if (channels.Contains(channel.ToUpper()) == true)
                {
                    channels.Remove(channel.ToUpper());
                    channelRemoved = true;
                }
            }
            if (channelRemoved)
            {
                character.SendMessage("Left Channel : " + channel.ToUpper(), "server");
                sendLeaveChannelNotification(channel.ToUpper());
                getChannels();
            }
        }
        public void getChannels()
        {
            StringWriter stringWriter = new StringWriter();
            XmlTextWriter xmldoc = new XmlTextWriter(stringWriter);

            xmldoc.WriteStartElement("channels");

            lock (channels)
            {
                foreach (string channel in channels)
                {
                    xmldoc.WriteStartElement("channel");
                    xmldoc.WriteAttributeString("id", channel);
                    xmldoc.WriteEndElement();
                }
            }

            xmldoc.WriteEndElement();
            xmldoc.Flush();

            xmldoc.Close();

            stringWriter.Flush();

            string result = stringWriter.ToString();

            try
            {
                character.ClientSocket.socket.BeginSend(result);
            }
            catch { }
        }

        public void save()
        {
            lock (channels)
            {
                SqlConnection MyCon = new SqlConnection(Managers.DBConnectionString);
                MyCon.Open();
                SqlTransaction MyTrans = MyCon.BeginTransaction();

                SqlCommand SQLCom = new SqlCommand();
                SQLCom.Connection = MyCon;
                SQLCom.CommandType = System.Data.CommandType.StoredProcedure;
                SQLCom.Transaction = MyTrans;

                try
                {
                    //Delete existing items from bank
                    SQLCom.CommandText = "Characters_ChatChannels_Delete";
                    SQLCom.Parameters.AddWithValue("@CharacterID", character.ID);
                    SQLCom.ExecuteNonQuery();

                    //Add new items to bank
                    SQLCom.CommandText = "Characters_ChatChannels_Insert";
                    //Character ID already exists from above query
                    SQLCom.Parameters.Add("@ChannelName", System.Data.SqlDbType.VarChar);
                    foreach (string channel in channels)
                    {
                        SQLCom.Parameters["@ChannelName"].Value = channel;
                        SQLCom.ExecuteNonQuery();
                    }

                    MyTrans.Commit();
                }
                catch
                {
                    MyTrans.Rollback();
                }
                finally
                {
                    MyCon.Close();
                    MyCon.Dispose();
                }
            }
        }
    }
}
